package org.linlinjava.litemall.admin.service;

import static org.linlinjava.litemall.admin.util.AdminResponseCode.ORDER_CONFIRM_NOT_ALLOWED;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.ORDER_NOT_EXIST;
import static org.linlinjava.litemall.admin.util.AdminResponseCode.ORDER_REFUND_FAILED;
import static org.linlinjava.litemall.db.beans.Constants.INTEGRAL_LOG_TYPE_RETURN;
import static org.linlinjava.litemall.db.domain.LitemallTopic.Column.goods;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.SneakyThrows;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shiro.SecurityUtils;
import org.linlinjava.litemall.admin.beans.Constants;
import org.linlinjava.litemall.admin.beans.enums.OrderStatusEnum;
import org.linlinjava.litemall.admin.beans.enums.PromptEnum;
import org.linlinjava.litemall.admin.beans.pojo.convert.BeanConvert;
import org.linlinjava.litemall.admin.beans.vo.OrderDayStatisticDetailVo;
import org.linlinjava.litemall.admin.beans.vo.OrderDetailGoodsVo;
import org.linlinjava.litemall.admin.beans.vo.OrderDetailVo;
import org.linlinjava.litemall.admin.beans.vo.OrderGoodsVo;
import org.linlinjava.litemall.admin.beans.vo.OrderVo;
import org.linlinjava.litemall.admin.controller.order.vo.AdminOrderDetailRespVO;
import org.linlinjava.litemall.admin.controller.order.vo.AdminSalesStatisticsReqVO;
import org.linlinjava.litemall.admin.controller.order.vo.AdminShopOrderDayStatisticsPageReqVO;
import org.linlinjava.litemall.admin.util.DateUtil;
import org.linlinjava.litemall.admin.util.PageUtil;
import org.linlinjava.litemall.admin.vo.goodsstatistics.GoodsStatisticGeneralRespVO;
import org.linlinjava.litemall.admin.vo.goodsstatistics.GoodsStatisticReqVO;
import org.linlinjava.litemall.admin.vo.goodsstatistics.GoodsStatisticRespVO;
import org.linlinjava.litemall.admin.vo.order.AdminLumiereOrderPageRespVO;
import org.linlinjava.litemall.admin.vo.order.OrderDayDetailReqVO;
import org.linlinjava.litemall.admin.vo.order.OrderTransactionDataReqVO;
import org.linlinjava.litemall.admin.vo.orderstatistics.HourStatisticsLineReqVO;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.payment.clover.service.UserCloverService;
import org.linlinjava.litemall.core.payment.paypal.service.impl.GoodsPaypalServiceImpl;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.BigDecimalUtil;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.AdminGoodsSalesStatisticsDTO;
import org.linlinjava.litemall.db.dto.LitemallAccountBookFormDto;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.BeanUtil;
import org.linlinjava.litemall.db.util.CollectionUtils;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.google.common.collect.Maps;

/**
 * 管理订单服务
 *
 * @author yliyun
 * @date 2022/09/14
 */
@Service
public class AdminOrderService {

    /**
     * 订单商品服务
     */
    @Autowired
    private LitemallOrderGoodsService orderGoodsService;

    @Autowired
    private LitemallMerchandiseService litemallMerchandiseService;
    @Autowired
    private LitemallShopMerchandiseService litemallShopMerchandiseService;
    @Autowired
    private LitemallOrderFormulaMaterialService litemallOrderFormulaMaterialService;

    @Autowired
    private LitemallOrderPackageService litemallOrderPackageService;
    /**
     * 店服务
     */
    @Autowired
    private LitemallShopService shopService;
    /**
     * 产品服务
     */
    @Autowired
    private LitemallGoodsProductService productService;
    /**
     * 用户服务
     */
    @Autowired
    private LitemallUserService userService;
    /**
     * 评论服务
     */
    @Autowired
    private LitemallCommentService commentService;
    /**
     * 日志助手
     */
    @Autowired
    private LogHelper logHelper;
    /**
     * 贝宝服务
     */
    @Autowired
    private GoodsPaypalServiceImpl paypalService;
    /**
     * 目录服务
     */
    @Autowired
    private LitemallCategoryService categoryService;
    @Autowired
    private LitemallGoodsRegionService litemallGoodsRegionService;
    /**
     * 商品服务
     */
    @Autowired
    private LitemallGoodsService goodsService;
    /**
     * 浏览记录服务
     */
    @Autowired
    private LitemallBrowseRecordService browseRecordService;
    /**
     * 订单记录服务
     */
    @Autowired
    private LitemallOrderRecordService orderRecordService;
    /**
     * 系统配置服务
     */
    @Autowired
    private LitemallSystemConfigService systemConfigService;
    /**
     * 注意助手
     */
    @Autowired
    private NoticeHelper noticeHelper;
    /**
     * litemall礼品卡用户服务
     */
    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;
    /**
     * litemall礼品卡用户日志服务
     */
    @Autowired
    private LitemallGiftCardUserLogService litemallGiftCardUserLogService;

    @Autowired
    private LitemallGiftCardOrderService litemallGiftCardOrderService;
    /**
     * litemall充电消费服务
     */
    @Autowired
    private LitemallRechargeConsumptionService litemallRechargeConsumptionService;
    /**
     * litemall订货配件服务
     */
    @Autowired
    private LitemallOrderGoodsAccessoryService litemallOrderGoodsAccessoryService;

    @Autowired
    private LitemallOrderGoodsPropertyService litemallOrderGoodsPropertyService;
    /**
     * litemall订单税务服务
     */
    @Autowired
    private LitemallOrderTaxService litemallOrderTaxService;

    /**
     * litemall退款服务
     */
    @Autowired
    private LitemallRefundService litemallRefundService;
    /**
     * litemall退还商品服务
     */
    @Autowired
    private LitemallRefundGoodsService litemallRefundGoodsService;
    /**
     * litemall退还税收服务
     */
    @Autowired
    private LitemallRefundTaxService litemallRefundTaxService;
    /**
     * 完整日志服务
     */
    @Autowired
    private LitemallIntegralLogService integralLogService;

    /**
     * litemall优惠券用户服务
     */
    @Autowired
    private LitemallCouponUserService litemallCouponUserService;

    @Autowired
    private LitemallOrderService litemallOrderService;

    @Autowired
    private LumiereOrderService lumiereOrderService;

    @Autowired
    private LumiereGoodsFormulaCorrelationService lumiereGoodsFormulaCorrelationService;

    @Autowired
    private LumiereFormulaSpecificationsService lumiereFormulaSpecificationsService;


    @Autowired
    private UserCloverService userCloverService;

    @Autowired
    private AwsNotifyService awsNotifyService;

    @Autowired
    private LitemallAccountBookService litemallAccountBookService;
    /**
     * 列表
     * 订单列表
     * 
     * @return {@link Object}
     */
    public ResponseUtil.Response list(AdminLumiereOrderPageRespVO respVO) {

        LambdaQueryWrapper<LitemallOrder> lambdaWrapper = new LambdaQueryWrapper<>();

        Optional.ofNullable(respVO.getOrderSn())
                .filter(StrUtil::isNotBlank)
                .ifPresent(sn -> lambdaWrapper.like(LitemallOrder::getOrderSn, sn));

        Optional.ofNullable(respVO.getOrderStatusArray())
                .filter(list -> !list.isEmpty())
                .ifPresent(list -> lambdaWrapper.in(LitemallOrder::getOrderStatus, list));

        Optional.ofNullable(respVO.getPayType())
                .filter(list -> !list.isEmpty())
                .ifPresent(list -> lambdaWrapper.in(LitemallOrder::getPayType, list));

        Optional.ofNullable(respVO.getOrderSource())
                .filter(list -> !list.isEmpty())
                .ifPresent(list -> lambdaWrapper.in(LitemallOrder::getOrderSource, list));

        Optional.ofNullable(respVO.getOrderType())
                .ifPresent(type -> lambdaWrapper.eq(LitemallOrder::getOrderType, type));

        Optional.ofNullable(respVO.getShopId())
                .ifPresent(shopId -> lambdaWrapper.eq(LitemallOrder::getShopId, shopId));

        // 新增对 userId 的 Optional 判空处理
        Optional.ofNullable(respVO.getUserId())
                .ifPresent(userId -> lambdaWrapper.eq(LitemallOrder::getUserId, userId));

        lambdaWrapper.orderByDesc(LitemallOrder::getPayTime);

        Optional.ofNullable(respVO.getDateRange())
                .filter(r -> r.length == 2 && r[0] != null && r[1] != null)
                .ifPresent(r -> lambdaWrapper.between(LitemallOrder::getAddTime, r[0], r[1]));

        IPage<LitemallOrder> orderList = litemallOrderService.page(new Page<>(respVO.getPage(), respVO.getLimit()),lambdaWrapper);
        orderList.getRecords().stream().forEach(litemallOrder->{
            LitemallShop shop = shopService.findById(litemallOrder.getShopId());
            LitemallUser user = userService.findById(litemallOrder.getUserId());
            litemallOrder.setUsername(ObjectUtil.isNotNull(user)?user.getUsername():"------");
            litemallOrder.setShopName(ObjectUtil.isNotNull(shop)?shop.getName():"------");
            litemallOrder.setOrderGoods(orderGoodsService.queryByOid(litemallOrder.getId()));
        });
        return ResponseUtil.okPage(orderList);
    }

    /**
     * 订单列表
     *
     * @param userName         用户名
     * @param id               id
     * @param userId           用户id
     * @param orderSn          订单sn
     * @param orderStatusArray 订单状态数组
     * @param orderType        订单类型
     * @param shopId           商店id
     * @param page             页面
     * @param limit            限制
     * @param sort             排序
     * @param order            订单
     * @return {@link Object}
     */
    public Object listInMember(String userName, Integer id,Integer userId, String orderSn, List<Short> orderStatusArray, Byte orderType, Integer shopId,
                       Integer page, Integer limit, String sort, String order) {
        List<LitemallUser> users = userService.findByName(userName);
        List<LitemallOrder> litemallOrders = null;
        if(users.size() > 0){
            List<Integer> userIds = users.stream().map(LitemallUser::getId).collect(Collectors.toList());
            litemallOrders = litemallOrderService.querySelective(id, userIds, orderSn, orderStatusArray, orderType, shopId, page, limit, sort, order);
        }else{
            litemallOrders = litemallOrderService.queryOrderWithUserId(userId);
        }

        //订单对应的门店
        List<Integer> ids = litemallOrders.stream().filter(o ->{
            return o.getShopId() != null;}).map(LitemallOrder::getShopId).collect(Collectors.toList());

        Map<Integer,LitemallUser> map = userService.queryAllApp().stream().collect(Collectors.toMap(LitemallUser::getId, user -> user));

        List<OrderVo> collect = litemallOrders.stream().map(o -> {
            LitemallShop shop = null;
            shop =shopService.findById(o.getShopId());
            return BeanConvert.toOrderVo(o, shop, o.getOrderSource().equals(Constants.ORDER_SOURCE_APP) == true ? map.get(o.getUserId()) : map.get(o.getMemberId()));
        }).collect(Collectors.toList());

        Pageable pageable = PageRequest.of(page - 1,limit);
        return ResponseUtil.ok(PageUtil.getPageLumierePayMemberUserLogVo(pageable,collect));
    }


    /**
     * 细节
     * 详情
     *
     * @param id id
     * @return {@link Object}
     */
    public Object detail(Integer id) {
        if(null == id){
            return ResponseUtil.badArgument();
        }
        LitemallOrder order = lumiereOrderService.getById(id);
        //LitemallOrder order = litemallOrderService.findById(id);
        Integer userId = order.getUserId();
        UserVo user = null != userId?userService.findUserVoById(userId):null;

        List<OrderDetailGoodsVo> goodsLs = new ArrayList<>();
        List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(order.getId());
        if(!CollUtil.isEmpty(orderGoods)) {
        	for (LitemallOrderGoods litemallOrderGoods : orderGoods) {
        		OrderDetailGoodsVo goodsVo = new OrderDetailGoodsVo();
        		BeanUtils.copyProperties(litemallOrderGoods, goodsVo);
        		//设置商品价格
        		goodsVo.setGoodsPrice(litemallOrderGoods.getSellingPrice().multiply(new BigDecimal(litemallOrderGoods.getNumber())));
        		goodsVo.setDiscountGoodsPrice(litemallOrderGoods.getDiscountPrice().multiply(new BigDecimal(litemallOrderGoods.getNumber())));
				Integer orderGoodsId = litemallOrderGoods.getId();

				//查询规格辅料
				String[] specifications = litemallOrderGoods.getSpecifications();
                goodsVo.setSpecifications(specifications[0]);
                String accessory = getGoodsAccessoryStr(orderGoodsId);
                goodsVo.setAccessory(accessory);
                String propertyStr = getGoodsPropertyStr(orderGoodsId);
                goodsVo.setProperty(propertyStr);
                //查询订单商品的税费表
				List<LitemallOrderTax> orderTaxs = litemallOrderTaxService.queryByOrderIdAndOrderGoodsId(id, orderGoodsId);
				goodsVo.setTaxs(orderTaxs);
        		goodsLs.add(goodsVo);
			}
        }
        AdminOrderDetailRespVO orderDetailResp = BeanUtil.copy(order, AdminOrderDetailRespVO.class);
        //礼物卡号
        if(orderDetailResp.getPayType() == Constants.ORDER_PAY_TYPE_CARD){
            LitemallGiftCardOrder giftCardOrder = litemallGiftCardOrderService.getByOrderId(orderDetailResp.getId());
            orderDetailResp.setGiftCardNo(giftCardOrder!=null?giftCardOrder.getCardNumber():"");
        }
        OrderDetailVo vo = new OrderDetailVo();
        vo.setOrder(orderDetailResp);
        vo.setGoodsLs(goodsLs);
        vo.setUser(user);
        return ResponseUtil.ok(vo);
    }

    /**
     * 获得商品配件str
     * 获取商品的辅料字符串
     *
     * @param orderGoodsId 订单商品id
     * @return {@link String}
     */
    private String getGoodsAccessoryStr(Integer orderGoodsId) {
    	StringBuffer sb = new StringBuffer();
        //配方
        List<LitemallOrderFormulaMaterial> orderFormulaMaterials = litemallOrderFormulaMaterialService
                .list(Wrappers.lambdaQuery(LitemallOrderFormulaMaterial.class)
                        .eq(LitemallOrderFormulaMaterial::getOrderGoodsId,orderGoodsId));
		if(!CollUtil.isEmpty(orderFormulaMaterials)) {
			for (int i = 0; i < orderFormulaMaterials.size(); i++) {
                LitemallOrderFormulaMaterial accessory = orderFormulaMaterials.get(i);
				sb.append(accessory.getMaterialName());
				if(accessory.getQuantity() >= 0) {
					sb.append("x");
				}
				sb.append(accessory.getQuantity());
                sb.append("\n");
			}
		}
		return sb.toString();
    }

    /**
     * 获得商品配件str
     * 获取商品的属性字符串
     *
     * @param orderGoodsId 订单商品id
     * @return {@link String}
     */
    private String getGoodsPropertyStr(Integer orderGoodsId) {
        StringBuffer sb = new StringBuffer();
        List<LitemallOrderGoodsProperty> orderGoodsProperties = litemallOrderGoodsPropertyService.queryByOrderGoodsId(orderGoodsId);
        if(!CollUtil.isEmpty(orderGoodsProperties)) {
            for (int i = 0; i < orderGoodsProperties.size(); i++) {
                LitemallOrderGoodsProperty property = orderGoodsProperties.get(i);
                sb.append(property.getName());
                sb.append(":");
                sb.append(property.getValue());
                sb.append("\n");
            }
        }
        return sb.toString();
    }

    /**
     * 退款
     * 订单退款
     * <p>
     * 1. 检测当前订单是否能够退款;
     * 2. 微信退款操作;
     * 3. 设置订单退款确认状态；
     * 4. 订单商品库存回库。
     * <p>
     * TODO
     * 虽然接入了微信退款API，但是从安全角度考虑，建议开发者删除这里微信退款代码，采用以下两步走步骤：
     * 1. 管理员登录微信官方支付平台点击退款操作进行退款
     * 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
     *
     * @param orderId 订单信息，{ orderId：xxx }
     * @param shopId  商店id
     * @return 订单退款操作结果
     */
    @Transactional
    public Object refund(Integer orderId, Integer shopId) {
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
        if (orderId == null) {
            return ResponseUtil.fail(111,"订单Id不能为空");
        }

        LitemallOrder order = litemallOrderService.findById(orderId);
        if(null != shopId && order.getShopId() != shopId){
            return ResponseUtil.fail(111,"门店不正确");
        }
        if (order == null) {
            return ResponseUtil.fail(111,"订单不存在");
        }

        // 如果订单不是退款状态，则不能退款
       if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {
            return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单状态不是退款状态,不能退款");
        }


        if(order.getPayType() == Constants.PAY_TYPE_PAYPAL.byteValue()){
            if(!paypalService.refund(order.getId())){
                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
            };
        }

        if(order.getPayType() == Constants.PAY_TYPE_BALANCE.byteValue()){
            if(!balanceRefund(order.getId())){
                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
            }
        }

        if(order.getPayType() == Constants.PAY_TYPE_GIFT_CARD.byteValue()){
            if(!giftCardRefund(order.getId())){
                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
            }
        }

        if(order.getPayType() == Constants.PAY_TYPE_POINT_EXCHANGE.byteValue()){
            if(!pointExchangeRefund(order.getId())){
                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退还积分失败");
            }
        }
        if(order.getPayType() == Constants.PAY_TYPE_CLOVER.byteValue()){
            if(!userCloverService.refund(orderId)){
                return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退还Clover失败");
            }
        }


        // 设置订单退款完成状态
        order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
        List<LitemallOrderGoods> orderGoodsLs = orderGoodsService.queryByOid(orderId);
        List<Pair<LitemallOrderGoods, Integer>> goods = new ArrayList<>();
        for (LitemallOrderGoods orderGoods : orderGoodsLs) {
            Integer canRefundNumber = orderGoods.getNumber() - orderGoods.getRefundNumber();
            if(canRefundNumber > 0 ) {
                Pair<LitemallOrderGoods, Integer> pair = Pair.of(orderGoods, canRefundNumber);
                goods.add(pair);
            }
        }
        refundDetail(shopId,order.getUserId(),null,null,order,goods);

        //订单获取积分从用户账户扣减
        if(order.getPayType() != Constants.PAY_TYPE_POINT_EXCHANGE.byteValue()){
           BigDecimal points =   order.getPoints();
           LitemallUser user = userService.findById(order.getUserId());

           if(points != null){
               if(points.compareTo(user.getPoints()) > 0){
                   return ResponseUtil.fail(111,"当前积分不足以匹配用户购买时赠送的积分,退款失败");
               }else{
                   user.setPoints(user.getPoints().subtract(points));
                   userService.updateById(user);

                   LitemallIntegralLog log = new LitemallIntegralLog();
                   log.setUserId(user.getId());
                   log.setType(INTEGRAL_LOG_TYPE_RETURN);
                   log.setOrderId(order.getId());
                   log.setPoints(user.getPoints());
                   log.setChangePoints(BigDecimal.ZERO.subtract(points));
                   //添加详细信息
                   log.setUseType(7);
                   log.setGoodsName(orderGoodsService.queryByOid(orderId).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()));
                   integralLogService.add(log);
               }
           }
        }


        LitemallUser litemallUser = userService.findById(order.getUserId());

        //TODO 记录退款数据
        /*if (litemallOrderService.updateWithOptimisticLocker(order) == 0) {
            throw new RuntimeException("更新数据已失效");
        }*/

        //商品
        if(CollUtil.isNotEmpty(order.getGoodsIds())){
            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.getOrderGoodsByIds(order.getGoodsIds());
            for (LitemallOrderGoods orderGoods : orderGoodsList) {
                List<LitemallOrderFormulaMaterial> orderFormulaMaterialList = litemallOrderFormulaMaterialService.selectByOrderGoodsIdList(orderGoods.getId());
                for (LitemallOrderFormulaMaterial orderFormulaMaterial : orderFormulaMaterialList) {
                    //对比每一个的库存
                    LitemallMerchandise merchandise = litemallMerchandiseService.findByName(orderFormulaMaterial.getMaterialName());
                    LitemallShopMerchandise shopMerchandise = litemallShopMerchandiseService.queryByMerIdAndShopId(merchandise.getId(), shopId);
                    shopMerchandise.setNumber(shopMerchandise.getNumber()+orderFormulaMaterial.getQuantity()*orderGoods.getNumber());
                    litemallShopMerchandiseService.updateById(shopMerchandise);
                }

            }
        }

        //套餐
        if(CollUtil.isNotEmpty(order.getPackageIds())){
            for (LitemallOrderPackage orderPackage : litemallOrderPackageService.listByIds(order.getPackageIds())) {
                List<LitemallOrderGoods> orderGoodsList = orderGoodsService.getOrderGoodsByIds(orderPackage.getGoodsIds());
                for (LitemallOrderGoods orderGoods : orderGoodsList) {
                    List<LitemallOrderFormulaMaterial> orderFormulaMaterialList = litemallOrderFormulaMaterialService.selectByOrderGoodsIdList(orderGoods.getId());
                    for (LitemallOrderFormulaMaterial orderFormulaMaterial : orderFormulaMaterialList) {
                        //对比每一个的库存
                        LitemallMerchandise merchandise = litemallMerchandiseService.findByName(orderFormulaMaterial.getMaterialName());
                        LitemallShopMerchandise shopMerchandise = litemallShopMerchandiseService.queryByMerIdAndShopId(merchandise.getId(), shopId);
                        shopMerchandise.setNumber(shopMerchandise.getNumber()+orderFormulaMaterial.getQuantity()*orderGoods.getNumber());
                        litemallShopMerchandiseService.updateById(shopMerchandise);
                    }
                }
            }
        }

        // 商品货品数量增加
        /*List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
        for (LitemallOrderGoods orderGoods : orderGoodsList) {
            List<LitemallGoodsProduct> products = productService.queryByGidAndSid(orderGoods.getGoodsId(),orderGoods.getShopId());
            if(products.size() > 0){
                LitemallGoodsProduct product = products.get(0);
                Integer productId = orderGoods.getProductId();
                Short number = orderGoods.getNumber();
                product.setId(productId);
                product.setNumber(product.getNumber()+number);
                productService.updateById(product);
            }else{
                products = productService.queryByGidAndSid(orderGoods.getGoodsId(),null);
                if(products.size() > 0){
                    LitemallGoodsProduct product = products.get(0);
                    Integer productId = orderGoods.getProductId();
                    Short number = orderGoods.getNumber();
                    product.setId(productId);
                    product.setNumber(product.getNumber()+number);
                    productService.updateById(product);
                }else{

                    return ResponseUtil.fail(111,"库存商品不存在");
                }

            }
        }*/

        addAccountBook(shopId,order.getActualPrice(),"POS order refund",1,2);


        //TODO 发送邮件和短信通知，这里采用异步发送
        // 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功，请耐心等待到账。”
        // 注意订单号只发后6位

        awsNotifyService.noticeMail("You have a refund",
                String.format("The order refund you applied for [ %s ] has been successful, please wait patiently for the receipt of the account.",order.getOrderSn()) ,
                String.format("The order refund you applied for [ %s ] has been successful, please wait patiently for the receipt of the account.",order.getOrderSn()),litemallUser.getEmail());
        awsNotifyService.sendSms(litemallUser.getMobile(),  String.format("The order refund you applied for [ %s ] has been successful, please wait patiently for the receipt of the account.",order.getOrderSn()), org.linlinjava.litemall.db.beans.Constants.AWS_MESSAGE_TYPE_PROMOTIONAL);

        logHelper.logOrderSucceed("退款", "订单编号 " + orderId);
        //消息推送和保存
        noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER,"You have a refund", String.format("The order refund you applied for [ %s ] has been successful, please wait patiently for the receipt of the account.",order.getOrderSn()), order.getUserId(), order);
            lock.unlock();
        return ResponseUtil.ok();
        } catch (Exception e) {
            e.printStackTrace();
            lock.unlock();
            return false;
        }
    }



    private void addAccountBook(Integer shopId, BigDecimal actualPrice, String remark, Integer recordType, Integer sourceType) {
        LitemallAccountBookFormDto form = new LitemallAccountBookFormDto();
        form.setShopId(shopId);
        form.setRecordType(recordType);
        form.setRecordDate(LocalDateTime.now());
        form.setAmount(actualPrice);
        form.setRemark(remark);
        form.setSourceType(sourceType);
        litemallAccountBookService.create(shopId, form);
    }
    /**
     * 船
     * 发货
     * 1. 检测当前订单是否能够发货
     * 2. 设置订单发货状态
     *
     * @param body 订单信息，{ orderId：xxx, shipSn: xxx, shipChannel: xxx }
     * @return 订单操作结果
     * 成功则 { errno: 0, errmsg: '成功' }
     * 失败则 { errno: XXX, errmsg: XXX }
     */
    public Object ship(String body) {
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        String shipSn = JacksonUtil.parseString(body, "shipSn");
        String shipChannel = JacksonUtil.parseString(body, "shipChannel");
        if (orderId == null || shipSn == null || shipChannel == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = litemallOrderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }

        // 如果订单不是已付款状态，则不能发货
        if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {
            return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
        }

        order.setOrderStatus(OrderUtil.STATUS_SHIP);
        order.setShipSn(shipSn);
        order.setShipChannel(shipChannel);
        order.setShipTime(LocalDateTime.now());
        if (litemallOrderService.updateWithOptimisticLocker(order) == 0) {
            return ResponseUtil.updatedDateExpired();
        }

        //TODO 发送邮件和短信通知，这里采用异步发送
        // 发货会发送通知短信给用户:          *
        // "您的订单已经发货，快递公司 {1}，快递单 {2} ，请注意查收"
//        notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});
//        notifyService.notifyMailTemplate("发货", NotifyType.SHIP, order.get);

        logHelper.logOrderSucceed("发货", "订单编号 " + orderId);
        //消息推送和保存
        noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER,"order delivery", "order number "+order.getOrderSn()+"delivery", order.getUserId(), order);
        return ResponseUtil.ok();
    }


    /**
     * 回复
     * 回复订单商品
     *
     * @param body 订单信息，{ orderId：xxx }
     * @return 订单操作结果
     * 成功则 { errno: 0, errmsg: '成功' }
     * 失败则 { errno: XXX, errmsg: XXX }
     */
    public Object reply(String body) {
        Integer commentId = JacksonUtil.parseInteger(body, "commentId");
        if (commentId == null || commentId == 0) {
            return ResponseUtil.badArgument();
        }
        // 目前只支持回复一次
/*        if (commentService.findById(commentId) != null) {
            return ResponseUtil.fail(ORDER_REPLY_EXIST, "订单商品已回复！");
        }*/
        String content = JacksonUtil.parseString(body, "content");
        if (StringUtils.isEmpty(content)) {
            return ResponseUtil.badArgument();
        }
        // 创建评价回复
        LitemallComment comment = new LitemallComment();
        comment.setType((byte) 2);
        comment.setValueId(commentId);
        comment.setContent(content);
        comment.setUserId(0);                 // 评价回复没有用
        comment.setStar((short) 0);           // 评价回复没有用
        comment.setHasPicture(false);        // 评价回复没有用
        comment.setPicUrls(new String[]{});  // 评价回复没有用
        commentService.save(comment);

        return ResponseUtil.ok();
    }

    /**
     * 备注
     * 备注订单商品
     *
     * @param body   订单信息，{ orderId：xxx }
     * @param shopId 商店id
     * @return 订单操作结果
     * 成功则 { errno: 0, errmsg: '成功' }
     * 失败则 { errno: XXX, errmsg: XXX }
     */
    public Object remark(String body, Integer shopId) {
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null || orderId == 0) {
            return ResponseUtil.badArgument();
        }
        // 目前只支持回复一次
        LitemallOrder order = litemallOrderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.fail(ORDER_NOT_EXIST, "订单不存在！");
        }
/*        if(shopId != null){
            if(!shopId.equals(order.getShopId())){
                return ResponseUtil.fail(ORDER_NOT_PERMISSION, "无权处理该订单！");
            }
        }*/
        String remark = JacksonUtil.parseString(body, "remark");
        if (StringUtils.isEmpty(remark)) {
            return ResponseUtil.badArgument();
        }
        // 创建备注
        LitemallAdmin admin = (LitemallAdmin)SecurityUtils.getSubject().getPrincipal();
        LitemallOrderRecord record = new LitemallOrderRecord();
        record.setOrderId(order.getId());
        record.setAddUserId(admin.getId());
        record.setOrderStatus(order.getOrderStatus());
        record.setPayStatus(order.getPayType());
        record.setRemark(remark);
        record.setShipStatus(order.getShipStatus());
        record.setUserId(admin.getId());
        record.setUserName(admin.getUsername());
        orderRecordService.add(record);


        return ResponseUtil.ok();
    }

    /**
     * 商品统计
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param shopId    商店id
     * @return {@link Object}
     */
    public Object goodsStatistics(String startTime, String endTime, Integer shopId){
        DateTimeFormatter timeDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        LocalDateTime startTimes = LocalDateTime.parse(startTime, timeDtf);
        LocalDateTime endTimes = LocalDateTime.parse(endTime, timeDtf);
        //订单数据
        LitemallOrder litemallOrder = litemallOrderService.queryGoodsStatistics(startTimes, endTimes, shopId);
        if(ObjectUtils.isEmpty(litemallOrder)){
            return ResponseUtil.ok(null);
        }
        Map<String, Object> map = Maps.newHashMap();
        //商品订单统计
        List<LitemallOrderGoods> orderGoods = getOrderGoods(orderGoodsService.queryGoodsStatistics(startTimes, endTimes, shopId, null));
        //商品统计
        map.put("orderGoods", orderGoods);
        //类目统计
        map.put("categorys", getCategory(orderGoods));
        return ResponseUtil.ok(map);
    }

    public Object goodsSalesStatisticsGeneral(GoodsStatisticReqVO reqVO) {
        List<Integer> goodsRegionIdsList = new ArrayList<>();
        if(reqVO.getRegionIds().size()>0){
            goodsRegionIdsList = CollectionUtils.convertList(litemallGoodsRegionService.selectByCityIdGoods(reqVO.getRegionIds().get(2)),LitemallGoodsRegion::getGoodsId);
            if(CollUtil.isEmpty(goodsRegionIdsList)){
                return ResponseUtil.ok(new GoodsStatisticGeneralRespVO());
            }
        }
        List<Integer> goodsIsOnSaleIdsList = new ArrayList<>();
        if(reqVO.getIsOnSale()!=null&&CollUtil.isEmpty(goodsIsOnSaleIdsList)){
            goodsIsOnSaleIdsList = CollectionUtils.convertList( goodsService.selectListByIsOnSale(reqVO.getIsOnSale()),LitemallGoods::getId);
            if(CollUtil.isEmpty(goodsIsOnSaleIdsList)){
                return ResponseUtil.ok(new GoodsStatisticGeneralRespVO());
            }
        }

        Collection<Integer> orderIdsList = new ArrayList<>();

        if (reqVO.getShopId() != null||reqVO.getOrderSource() != null||reqVO.getPayType() != null) {
            List<LitemallOrder> orders = litemallOrderService.list(
                    Wrappers.lambdaQuery(LitemallOrder.class)
                            .eq(reqVO.getShopId() != null,LitemallOrder::getShopId, reqVO.getShopId())
                            .eq(reqVO.getPayType() != null,LitemallOrder::getPayType, reqVO.getPayType())
                            .eq(reqVO.getOrderSource() != null,LitemallOrder::getOrderSource, reqVO.getOrderSource())
            );
            orderIdsList = CollStreamUtil.toSet(orders, LitemallOrder::getId);
            if (CollUtil.isEmpty(orderIdsList)) {
                return ResponseUtil.ok(new GoodsStatisticGeneralRespVO());
            }
        }

        LambdaQueryWrapper<LitemallOrderGoods> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.in(goodsRegionIdsList.size()>0,LitemallOrderGoods::getGoodsId, goodsRegionIdsList);
        orderWrapper.in(goodsIsOnSaleIdsList.size()>0,LitemallOrderGoods::getGoodsId,goodsIsOnSaleIdsList);
        orderWrapper.in(reqVO.getShopId()!=null||reqVO.getOrderSource()!=null||reqVO.getPayType() != null,LitemallOrderGoods::getOrderId,orderIdsList);
        orderWrapper.eq(reqVO.getGoodsId() != null, LitemallOrderGoods::getGoodsId, reqVO.getGoodsId());
        orderWrapper.eq(reqVO.getCategoryl3() != null, LitemallOrderGoods::getCategoryId, reqVO.getCategoryl3());
        Optional.ofNullable(reqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> orderWrapper.between(LitemallOrderGoods::getAddTime, range[0], range[1]));

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.selectList(orderWrapper);

        //计算 付款人数 卖出件数 总销售金额
        Long totalPayUserNum = orderGoodsList.stream()
                .map(LitemallOrderGoods::getOrderId)
                .distinct()
                .count();

        int totalSalesNum = orderGoodsList.stream()
                .mapToInt(LitemallOrderGoods::getNumber)
                .sum();
        BigDecimal totalActualPrice = BigDecimalUtil.sum(orderGoodsList,LitemallOrderGoods::getPrice);

        // 计算税费
        List<LitemallOrderTax> orderTaxAllList = new ArrayList<>();
        for (LitemallOrderGoods litemallOrderGoods : orderGoodsList) {
            orderTaxAllList.addAll(litemallOrderTaxService.queryByOrderIdAndOrderGoodsId(litemallOrderGoods.getOrderId(), litemallOrderGoods.getId()));
        }
        BigDecimal totalGstTaxPrice = BigDecimalUtil.sum(orderTaxAllList,LitemallOrderTax::getPrice,item -> LitemallTax.TAX_GST.equals(item.getCode()));
        BigDecimal totalHstTaxPrice = BigDecimalUtil.sum(orderTaxAllList,LitemallOrderTax::getPrice,item -> LitemallTax.TAX_HST.equals(item.getCode()));
        BigDecimal totalPstTaxPrice = BigDecimalUtil.sum(orderTaxAllList,LitemallOrderTax::getPrice,item -> LitemallTax.TAX_PST.equals(item.getCode()));

        LambdaQueryWrapper<LitemallOrderGoods> refundOrderWrapper = new LambdaQueryWrapper<>();
        refundOrderWrapper.in(reqVO.getShopId()!=null||reqVO.getOrderSource()!=null||reqVO.getPayType() != null,LitemallOrderGoods::getOrderId,orderIdsList);
        refundOrderWrapper.eq(reqVO.getGoodsId() != null, LitemallOrderGoods::getGoodsId, reqVO.getGoodsId());
        refundOrderWrapper.eq(reqVO.getCategoryl3() != null, LitemallOrderGoods::getCategoryId, reqVO.getCategoryl3());
        refundOrderWrapper.in(goodsRegionIdsList.size()>0,LitemallOrderGoods::getGoodsId, goodsRegionIdsList);
        refundOrderWrapper.in(goodsIsOnSaleIdsList.size()>0,LitemallOrderGoods::getGoodsId,goodsIsOnSaleIdsList);
        refundOrderWrapper.gt(LitemallOrderGoods::getRefundNumber,0);
        Optional.ofNullable(reqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> refundOrderWrapper.between(LitemallOrderGoods::getAddTime, range[0], range[1]));

        List<LitemallOrderGoods> refundOrderGoodsList = orderGoodsService.selectList(refundOrderWrapper);

        // 累计退款统计
        Long totalRefundUserNum =  refundOrderGoodsList.stream()
                .map(LitemallOrderGoods::getOrderId)
                .distinct()
                .count();;
        int totalRefundNum = refundOrderGoodsList.stream().mapToInt(LitemallOrderGoods::getNumber).sum();
        BigDecimal totalRefundActualPrice = BigDecimalUtil.sum(refundOrderGoodsList,LitemallOrderGoods::getPrice);

        // 最后，将所有总计结果设置到一个 GoodsStatisticRespVO 对象中
        GoodsStatisticGeneralRespVO totalStatistic = new GoodsStatisticGeneralRespVO();
        totalStatistic.setGoodsNum(CollectionUtils.convertSet(orderGoodsList,LitemallOrderGoods::getGoodsId).size());
        totalStatistic.setPayUserNum(totalPayUserNum.intValue());
        totalStatistic.setSalesNum(totalSalesNum);
        totalStatistic.setActualPrice(totalActualPrice);
        totalStatistic.setGstTaxPrice(totalGstTaxPrice);
        totalStatistic.setHstTaxPrice(totalHstTaxPrice);
        totalStatistic.setPstTaxPrice(totalPstTaxPrice);
        totalStatistic.setRefundUserNum(totalRefundUserNum.intValue());
        totalStatistic.setRefundNum(totalRefundNum);
        totalStatistic.setRefundActualPrice(totalRefundActualPrice);

        return ResponseUtil.ok(totalStatistic);
    }


    public Object goodsSalesStatistics(GoodsStatisticReqVO reqVO){
        List<Integer> goodsRegionIdsList = new ArrayList<>();
        if(reqVO.getRegionIds().size()>0){
            goodsRegionIdsList = CollectionUtils.convertList(litemallGoodsRegionService.selectByCityIdGoods(reqVO.getRegionIds().get(2)),LitemallGoodsRegion::getGoodsId);
            if(CollUtil.isEmpty(goodsRegionIdsList)){
                return ResponseUtil.okPage(new Page<>());
            }
        }
        List<Integer> goodsIsOnSaleIdsList = new ArrayList<>();
        if(reqVO.getIsOnSale()!=null&&CollUtil.isEmpty(goodsIsOnSaleIdsList)){
            goodsIsOnSaleIdsList = CollectionUtils.convertList( goodsService.selectListByIsOnSale(reqVO.getIsOnSale()),LitemallGoods::getId);
            if(CollUtil.isEmpty(goodsIsOnSaleIdsList)){
                return ResponseUtil.okPage(new Page<>());
            }
        }
        
        Page<LitemallGoods> goodsPage = goodsService.selectPage(new Page(reqVO.getPage(), reqVO.getLimit()), Wrappers.lambdaQuery(LitemallGoods.class)
                //.eq(reqVO.getShopId()!=null,LitemallGoods::getShopId,reqVO.getShopId())
                .in(goodsRegionIdsList.size()>0,LitemallGoods::getId, goodsRegionIdsList)
                .in(goodsIsOnSaleIdsList.size()>0,LitemallGoods::getId,goodsIsOnSaleIdsList)
                .eq(reqVO.getGoodsId() != null, LitemallGoods::getId, reqVO.getGoodsId())
                .eq(reqVO.getCategoryl3() != null, LitemallGoods::getCategoryId, reqVO.getCategoryl3())
                .in(LitemallGoods::getId,CollStreamUtil.toSet(orderGoodsService.selectList(Wrappers.lambdaQuery()),LitemallOrderGoods::getGoodsId))
                .eq(reqVO.getIsOnSale() != null, LitemallGoods::getIsOnSale, reqVO.getIsOnSale()));

        Collection<Integer> orderIdsList = new ArrayList<>();

        if (reqVO.getShopId() != null || reqVO.getOrderSource() != null||reqVO.getPayType() != null) {
            List<LitemallOrder> orders = litemallOrderService.list(
                    Wrappers.lambdaQuery(LitemallOrder.class)
                            .eq(reqVO.getShopId() != null,LitemallOrder::getShopId, reqVO.getShopId())
                            .eq(reqVO.getPayType() != null,LitemallOrder::getPayType, reqVO.getPayType())
                            .eq(reqVO.getOrderSource() != null,LitemallOrder::getOrderSource, reqVO.getOrderSource())
            );
            orderIdsList = CollStreamUtil.toSet(orders, LitemallOrder::getId);
            if (CollUtil.isEmpty(orderIdsList)) {
                return ResponseUtil.okPage(new Page<>());
            }
        }

        List<GoodsStatisticRespVO> goodsStatisticList = new ArrayList<>();
        for (LitemallGoods goods : goodsPage.getRecords()) {
            GoodsStatisticRespVO  goodsStatisticRespVO = new GoodsStatisticRespVO();
            LitemallCategory litemallCategory = categoryService.findById(goods.getCategoryId());
            goodsStatisticRespVO.setGoodsName(goods.getName());
            goodsStatisticRespVO.setGoodsId(goods.getId());
            goodsStatisticRespVO.setCategorylName(litemallCategory.getName());
            goodsStatisticRespVO.setIsOnSale(goods.getIsOnSale());
            goodsStatisticRespVO.setUnit(goods.getUnit());


            LambdaQueryWrapper<LitemallOrderGoods> orderWrapper = new LambdaQueryWrapper<>();
            orderWrapper.in(reqVO.getShopId()!=null||reqVO.getOrderSource()!=null||reqVO.getPayType() != null,LitemallOrderGoods::getOrderId,orderIdsList);
            orderWrapper.eq(LitemallOrderGoods::getGoodsId, goods.getId());
            Optional.ofNullable(reqVO.getDateRange())
                    .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                    .ifPresent(range -> orderWrapper.between(LitemallOrderGoods::getAddTime, range[0], range[1]));

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.selectList(orderWrapper);

            //计算 付款人数 卖出件数 总销售金额
            long payUserNum = orderGoodsList.stream()
                    .map(LitemallOrderGoods::getOrderId)
                    .distinct()
                    .count();
            goodsStatisticRespVO.setPayUserNum((int) payUserNum);
            goodsStatisticRespVO.setSalesNum(orderGoodsList.stream()
                    .mapToInt(LitemallOrderGoods::getNumber)
                    .sum());
            goodsStatisticRespVO.setActualPrice(BigDecimalUtil.sum(orderGoodsList,LitemallOrderGoods::getPrice));

            //计算税费
            List<LitemallOrderTax> orderTaxAllList = new ArrayList<>();
            for (LitemallOrderGoods litemallOrderGoods : orderGoodsList) {
                List<LitemallOrderTax> orderTaxList = litemallOrderTaxService.queryByOrderIdAndOrderGoodsId(litemallOrderGoods.getOrderId(), litemallOrderGoods.getId());
                orderTaxAllList.addAll(orderTaxList);
            }
            goodsStatisticRespVO.setGstTaxPrice(BigDecimalUtil.sum(orderTaxAllList,LitemallOrderTax::getPrice,item -> LitemallTax.TAX_GST.equals(item.getCode())));
            goodsStatisticRespVO.setHstTaxPrice(BigDecimalUtil.sum(orderTaxAllList,LitemallOrderTax::getPrice,item -> LitemallTax.TAX_HST.equals(item.getCode())));
            goodsStatisticRespVO.setPstTaxPrice(BigDecimalUtil.sum(orderTaxAllList,LitemallOrderTax::getPrice,item -> LitemallTax.TAX_PST.equals(item.getCode())));

            LambdaQueryWrapper<LitemallOrderGoods> refundOrderWrapper = new LambdaQueryWrapper<>();
            refundOrderWrapper.in(reqVO.getShopId()!=null||reqVO.getOrderSource()!=null||reqVO.getPayType() != null,LitemallOrderGoods::getOrderId,orderIdsList);
            refundOrderWrapper.eq(LitemallOrderGoods::getGoodsId, goods.getId());
            refundOrderWrapper.gt(LitemallOrderGoods::getRefundNumber,0);
            Optional.ofNullable(reqVO.getDateRange())
                    .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                    .ifPresent(range -> refundOrderWrapper.between(LitemallOrderGoods::getAddTime, range[0], range[1]));

            List<LitemallOrderGoods> refundOrderGoodsList = orderGoodsService.selectList(refundOrderWrapper);

            //计算退款的
            long RefundUserNum = refundOrderGoodsList.stream()
                    .map(LitemallOrderGoods::getOrderId)
                    .distinct()
                    .count();
            goodsStatisticRespVO.setRefundUserNum((int)RefundUserNum);
            goodsStatisticRespVO.setRefundNum(refundOrderGoodsList.stream()
                    .mapToInt(LitemallOrderGoods::getNumber)
                    .sum());
            goodsStatisticRespVO.setRefundActualPrice(BigDecimalUtil.sum(refundOrderGoodsList,LitemallOrderGoods::getPrice));

            LumiereGoodsFormulaCorrelation formulaByGoodsId = lumiereGoodsFormulaCorrelationService.getGoodsFormulaByGoodsId(goods.getId());
            Map<String, List<LitemallOrderGoods>> orderGoodsMap =
                    CollStreamUtil.groupByKey(orderGoodsList, og -> og.getSpecifications()[0]);

            Map<String, List<LitemallOrderGoods>> refundOrderGoodsMap =
                    CollStreamUtil.groupByKey(refundOrderGoodsList, og -> og.getSpecifications()[0]);

            List<GoodsStatisticRespVO.Item> itemList = new ArrayList<>();
            for (LumiereFormulaSpecifications lumiereFormulaSpecifications : lumiereFormulaSpecificationsService.selectListByFormulaId(formulaByGoodsId.getFormulaId())) {
                GoodsStatisticRespVO.Item item = new GoodsStatisticRespVO.Item();
                item.setSpecificationsName(lumiereFormulaSpecifications.getSpecificationsName());

                List<LitemallOrderGoods> orderGoodsList1 = orderGoodsMap.get(lumiereFormulaSpecifications.getSpecificationsName());
                if(orderGoodsList1==null)continue;
                //计算 付款人数 卖出件数 总销售金额

                item.setPayUserNum((int) orderGoodsList1.stream()
                        .map(LitemallOrderGoods::getOrderId)
                        .distinct()
                        .count());
                item.setSalesNum(orderGoodsList1.stream()
                        .mapToInt(LitemallOrderGoods::getNumber)
                        .sum());
                item.setActualPrice(BigDecimalUtil.sum(orderGoodsList1,LitemallOrderGoods::getPrice));
                //计算税费
                List<LitemallOrderTax> orderTaxAllList1 = new ArrayList<>();
                for (LitemallOrderGoods litemallOrderGoods : orderGoodsList1) {
                    List<LitemallOrderTax> orderTaxList1 = litemallOrderTaxService.queryByOrderIdAndOrderGoodsId(litemallOrderGoods.getOrderId(), litemallOrderGoods.getId());
                    orderTaxAllList1.addAll(orderTaxList1);
                }
                item.setGstTaxPrice(BigDecimalUtil.sum(orderTaxAllList1,LitemallOrderTax::getPrice,item1 -> LitemallTax.TAX_GST.equals(item1.getCode())));
                item.setHstTaxPrice(BigDecimalUtil.sum(orderTaxAllList1,LitemallOrderTax::getPrice,item1 -> LitemallTax.TAX_HST.equals(item1.getCode())));
                item.setPstTaxPrice(BigDecimalUtil.sum(orderTaxAllList1,LitemallOrderTax::getPrice,item1 -> LitemallTax.TAX_PST.equals(item1.getCode())));

                List<LitemallOrderGoods> orderGoodsList2 = refundOrderGoodsMap.get(lumiereFormulaSpecifications.getSpecificationsName());
                if(orderGoodsList2==null)orderGoodsList2 =new ArrayList<>();
                //计算退款的
                item.setRefundUserNum((int)orderGoodsList2.stream()
                        .map(LitemallOrderGoods::getOrderId)
                        .distinct()
                        .count());
                item.setRefundNum(orderGoodsList2.stream()
                        .mapToInt(LitemallOrderGoods::getNumber)
                        .sum());
                item.setRefundActualPrice(BigDecimalUtil.sum(orderGoodsList2,LitemallOrderGoods::getPrice));
                itemList.add(item);
            }
            goodsStatisticRespVO.setItems(itemList);

            goodsStatisticList.add(goodsStatisticRespVO);
        }
        return  ResponseUtil.okPage(goodsPage,goodsStatisticList);
    }


    @SneakyThrows
    public Object salesStatistics(AdminSalesStatisticsReqVO reqVO){
        LambdaQueryWrapper<LitemallOrder> queryWrapper =new LambdaQueryWrapper<>();

        Optional.ofNullable(reqVO.getShopId()).ifPresent(shopId -> queryWrapper.eq(LitemallOrder::getShopId, shopId));
        Optional.ofNullable(reqVO.getPayType()).ifPresent(payType -> queryWrapper.eq(LitemallOrder::getPayType, payType));
        Optional.ofNullable(reqVO.getOrderSource())
                .filter(list -> !list.isEmpty())
                .ifPresent(list -> queryWrapper.in(LitemallOrder::getOrderSource, list));
        Optional.ofNullable(reqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> queryWrapper.between(LitemallOrder::getAddTime, range[0], range[1]));
        //订单查询
        List<LitemallOrder> litemallOrder = litemallOrderService.list(queryWrapper);
        //没有订单就直接返回
        if(CollUtil.isEmpty(litemallOrder)){
            return ResponseUtil.fail(PromptEnum.P_102.getCode(), PromptEnum.P_102.getDesc());
        }
        Map<String, Object> map = Maps.newHashMap();
        //浏览人数
        LambdaQueryWrapper<LitemallBrowseRecord> browseRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        Optional.ofNullable(reqVO.getShopId()).ifPresent(shopId -> browseRecordLambdaQueryWrapper.eq(LitemallBrowseRecord::getShopId, shopId));
        Optional.ofNullable(reqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> browseRecordLambdaQueryWrapper.between(LitemallBrowseRecord::getAddTime, range[0], range[1]));

        List<LitemallBrowseRecord> browseRecords = browseRecordService.list(browseRecordLambdaQueryWrapper);
        map.put("browseUserNum", !CollUtil.isEmpty(browseRecords)?browseRecords.size():0);

        //下单人数
        map.put("userOrderNum", CompletableFuture.supplyAsync(()->litemallOrder.stream().map(LitemallOrder::getId).distinct().count()).get());
        //订单数
        map.put("orderNum", !CollUtil.isEmpty(litemallOrder)?litemallOrder.size():0);

        //下单件数
        List<Integer> orderIds =  litemallOrder.stream().map(LitemallOrder::getId).distinct().collect(Collectors.toList());
        map.put("orderGoodsNum",CompletableFuture.supplyAsync(()->orderGoodsService.orderGoodsNum(orderIds)).get());

        //过滤 取消和自动取消 退款和自动退款状态
        List<LitemallOrder> ordreList = litemallOrder.stream()
                .filter(order -> !(Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_102.getCode() || Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_103.getCode() || Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_202.getCode() || Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_203.getCode())).collect(Collectors.toList());
        //有效订单数
        map.put("validOrderNum", !CollUtil.isEmpty(ordreList)?ordreList.size():0);

        //下单金额
        BigDecimal b = new BigDecimal(litemallOrder.stream().mapToDouble(order ->reqVO.getPayType()!=null&& reqVO.getPayType()==6?Double.valueOf(order.getPoints().toString()):Double.valueOf(order.getOrderPrice().toString())).sum());
        map.put("orderPrice", b.setScale(2, BigDecimal.ROUND_HALF_UP));

        //退款中人数
        map.put("underRefundUsers",CompletableFuture.supplyAsync(()->litemallOrder.stream().filter(order->order.getOrderStatus()==202).count()).get());

        //退款金额
        map.put("refundPrice", litemallOrder.stream()
                .filter(order -> Integer.valueOf(order.getOrderStatus()).equals(OrderStatusEnum.P_202.getCode()) || Integer.valueOf(order.getOrderStatus()).equals(OrderStatusEnum.P_203.getCode()))
                .mapToDouble(refund-> reqVO.getPayType()!=null&&reqVO.getPayType()==6?Double.valueOf(refund.getPoints().toString()):Double.valueOf(refund.getActualPrice().toString())).sum());

        //付款人数 过滤下单和取消订单状态 再人员分组
        map.put("payUserNum", CompletableFuture.supplyAsync(()->litemallOrder.stream().filter(order -> {
            return Arrays.asList(new String[]{"101", "201", "202", "203", "301", "401", "402"}).contains(Integer.toString(order.getOrderStatus()));
        }).map(LitemallOrder::getId).distinct().count()).get());



        List<LitemallOrder> collect1 = litemallOrder.stream()
                .filter(order -> !(Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_101.getCode() || Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_102.getCode() || Integer.valueOf(order.getOrderStatus()) == OrderStatusEnum.P_103.getCode()))
                .collect(Collectors.toList());
        //付款订单数
        map.put("payOrderNum", !CollUtil.isEmpty(collect1)?collect1.size():0);
        //付款件数
        List<Integer> PayOrderGoodsNumOrderIds= litemallOrder.stream()
                .filter(order->order.getOrderStatus()!=102||order.getOrderStatus()!=103)
                .map(LitemallOrder::getId).collect(Collectors.toList());
        map.put("PayOrderGoodsNum",CompletableFuture.supplyAsync(()->orderGoodsService.PayOrderGoodsNum(PayOrderGoodsNumOrderIds)).get());

        //付款金额
        BigDecimal bd = new BigDecimal(collect1.stream().mapToDouble(cc->reqVO.getPayType()!=null&&reqVO.getPayType()==6?Double.valueOf(cc.getPoints().toString()):Double.valueOf(cc.getActualPrice().toString())).sum());
        map.put("payPrice", bd.setScale(2, BigDecimal.ROUND_HALF_UP));

        //退款完成人数
        map.put("completefundUsers",CompletableFuture.supplyAsync(()->litemallOrder.stream().filter(order->order.getOrderStatus()==203).count()).get());
        return ResponseUtil.ok(map);
    }

    public Object transactionData(OrderTransactionDataReqVO reqVO){
        if(ArrayUtil.isEmpty(reqVO.getTimeHorizon())){
            return ResponseUtil.badArgument();
        }

        // 订单查询
        LambdaQueryWrapper<LitemallOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(reqVO.getShopId() != null, LitemallOrder::getShopId, reqVO.getShopId());
        lambdaQueryWrapper.between(LitemallOrder::getAddTime, reqVO.getTimeHorizon()[0], reqVO.getTimeHorizon()[1]);
        lambdaQueryWrapper.eq(reqVO.getPayType() != null, LitemallOrder::getPayType, reqVO.getPayType());
        lambdaQueryWrapper.eq(reqVO.getOrderSource() != null, LitemallOrder::getOrderSource, reqVO.getOrderSource());
        List<LitemallOrder> litemallOrder = litemallOrderService.selectList(lambdaQueryWrapper);
        List<String> amounts = getAmountRanges();
        if(CollUtil.isEmpty(litemallOrder)){
            LinkedHashMap<String, Object> map = Maps.newLinkedHashMap();
            for(String amountRange : amounts){
                map.put(amountRange, 0);
            }
            return ResponseUtil.ok(map);
        }
        LinkedHashMap<String, Object> map = Maps.newLinkedHashMap();
        for(String amountRange : amounts){
            String[] amountArr = amountRange.split("-");
            if(amountArr.length != 2){
                continue;
            }
            BigDecimal start = new BigDecimal(amountArr[0]);
            BigDecimal end = new BigDecimal(amountArr[1]);
            map.put(amountRange, getActualPrice(litemallOrder, reqVO.getPayType(), start, end));
        }
        return ResponseUtil.ok(map);
    }

    private List<String> getAmountRanges() {
        Map<String, String> data = systemConfigService.listAmount();
        if(data != null){
            String str = data.get(SystemConfig.LITEMALL_STATISTICS_AMOUNT);
            if(!StringUtils.isEmpty(str)){
                return new ArrayList<>(Arrays.asList(str.split(";")));
            }
        }
        return Arrays.asList("0-50", "50-100", "100-200", "200-500", "500-1000", "1000-5000", "5000-10000");
    }

    private int getActualPrice(List<LitemallOrder> orders, Byte payType, BigDecimal start, BigDecimal end) {
        return (int) orders.stream().filter(order -> {
            BigDecimal value = payType != null && payType == 6 ? order.getPoints() : order.getActualPrice();
            if (value == null) return false;
            return value.compareTo(start) > 0 && value.compareTo(end) <= 0;
        }).count();
    }


    /**
     * 查询订单完成id
     * 根据订单ID 查询订单是否完成 或者已评价 1：已完成 2：已评价 3：未完成
     *
     * @param orderGoodsId 订单商品id
     * @return {@link Object}
     */
    public Object queryOrderIsCompletionById(Integer orderGoodsId){

        LitemallOrderGoods orderGoods = orderGoodsService.findById(orderGoodsId);
        if(commentService.findById(orderGoods.getComment()) != null){
            return ResponseUtil.ok(2);
        }
        LitemallOrder order = litemallOrderService.findById(orderGoods.getOrderId());
        if(order.getOrderStatus().toString().equals(OrderStatusEnum.P_401) || order.getOrderStatus().toString().equals(OrderStatusEnum.P_402)){
            return ResponseUtil.ok(1);
        }
        return ResponseUtil.ok(3);
    }


    /**
     * 得到类别信息
     *
     * @param shopId     商店id
     * @param page       页面
     * @param limit      限制
     * @param sort       排序
     * @param order      订单
     * @param startTimes 开始时间
     * @param endTimes   结束时间
     * @return {@link List}<{@link Map}<{@link String}, {@link Object}>>
     */
    private List<Map<String, Object>> getCategoryInfo(Integer shopId, Integer page, Integer limit, String sort, String order, LocalDateTime startTimes, LocalDateTime endTimes) {
        //时间段内商品类目 销售总额 goodsId, goodsName, salesNum(销售件数), actualPrice(金额)
        List<Map<String, Object>> maps;
        maps = litemallOrderService.queryGoodsCategorySales(startTimes, endTimes, page, limit);
        if(!CollUtil.isEmpty(maps)){
            maps.stream().forEach(map -> {
                Integer cId = (Integer)map.get("categoryId");
                //查询商品浏览量
                List<LitemallBrowseRecord> litemallBrowseRecords = browseRecordService.querySelective(null, cId, startTimes, endTimes, page, limit, sort, order,shopId);
                if(!CollUtil.isEmpty(litemallBrowseRecords)){
                    //商品浏览量 browseNum
                    Integer browseNum = litemallBrowseRecords.size();
                    map.put("browseNum", browseNum);
                    //浏览人数
                    List<LitemallBrowseRecord> browses = litemallBrowseRecords.stream().collect(Collectors
                            .collectingAndThen(
                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(LitemallBrowseRecord::getBrowseUserId))),
                                    ArrayList::new));
                    Integer browseUserNum = browses.size();
                    map.put("browseUserNum", browseUserNum);
                    //付款人数
                    //根据商品类目ID查询订单
                    List<LitemallOrderGoods> litemallOrderGoods = orderGoodsService.queryGoodsSalesStatistics(null, cId, startTimes, endTimes, page, limit, sort, order);
                    map.put("payUserNum", !CollUtil.isEmpty(litemallOrderGoods) ? litemallOrderGoods.size() : 0);
                    //单品转化率
                    map.put("goodsConversionRate", browseNum/Integer.valueOf(map.get("salesNum").toString()));
                }else{
                    //浏览人数
                    map.put("browseUserNum", 0);
                    //商品浏览量
                    map.put("browseNum", 0);
                    //付款人数
                    map.put("payUserNum", 0);
                    //单品转化率
                    map.put("goodsConversionRate", 0);
                }
            });
        }
        return maps;
    }

    /**
     * 得到货物信息
     *
     * @param shopId     商店id
     * @param page       页面
     * @param limit      限制
     * @param sort       排序
     * @param order      订单
     * @param startTimes 开始时间
     * @param endTimes   结束时间
     * @return {@link List}<{@link Map}<{@link String}, {@link Object}>>
     */
    private List<Map<String, Object>> getGoodsInfo(Integer shopId, Integer page, Integer limit, String sort, String order, LocalDateTime startTimes, LocalDateTime endTimes) {
        //时间段内商品销售总额 goodsId, goodsName, salesNum(销售件数), actualPrice(金额)
        List<Map<String, Object>> maps = litemallOrderService.queryGoodsSales(shopId, startTimes, endTimes, page, limit);
        if(!CollUtil.isEmpty(maps)){
            maps.stream().forEach(map -> {
                Integer gId = (Integer)map.get("goodsId");
                //查询商品浏览量
                List<LitemallBrowseRecord> litemallBrowseRecords = browseRecordService.querySelective(gId, null, startTimes, endTimes, page, limit, sort, order,shopId);
                if(!CollUtil.isEmpty(litemallBrowseRecords)){
                    //商品浏览量 browseNum
                    Integer browseNum = litemallBrowseRecords.size();
                    map.put("browseNum", browseNum);
                    //浏览人数
                    List<LitemallBrowseRecord> browses = litemallBrowseRecords.stream().collect(Collectors
                            .collectingAndThen(
                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(LitemallBrowseRecord::getBrowseUserId))),
                                    ArrayList::new));
                    Integer browseUserNum = browses.size();
                    map.put("browseUserNum", browseUserNum);
                    //付款人数
                    //根据商品ID查询订单
                    List<LitemallOrderGoods> litemallOrderGoods = orderGoodsService.queryGoodsStatistics(startTimes, endTimes, shopId, gId);
                    List<LitemallOrderGoods> orders = litemallOrderGoods.stream().collect(Collectors
                            .collectingAndThen(
                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(LitemallOrderGoods::getOrderId))),
                                    ArrayList::new));
                    map.put("payUserNum", !CollUtil.isEmpty(orders) ? orders.size() : 0);
                    //单品转化率
                    map.put("goodsConversionRate", browseNum/Integer.valueOf(map.get("salesNum").toString()));
                }else{
                    //浏览人数
                    map.put("browseUserNum", 0);
                    //商品浏览量
                    map.put("browseNum", 0);
                    //付款人数
                    map.put("payUserNum", 0);
                    //单品转化率
                    map.put("goodsConversionRate", 0);
                }
            });
        }
        return maps;
    }


    /**
     * 得到类别
     *
     * @param orderGoods 订单货物
     * @return {@link List}<{@link OrderGoodsVo}>
     */
    private List<OrderGoodsVo> getCategory(List<LitemallOrderGoods> orderGoods) {
        List<OrderGoodsVo> orderGoodsVos = new ArrayList<>();
        orderGoods.stream().forEach(og->{
            OrderGoodsVo orderGoodsVo = new OrderGoodsVo();
            LitemallCategory category = categoryService.findById(og.getCategoryId());
            BeanUtils.copyProperties(og, orderGoodsVo);
            orderGoodsVo.setCategoryId(category.getId());
            orderGoodsVo.setCategoryName(category.getName());
            orderGoodsVo.setNumber(og.getNumber());
            orderGoodsVos.add(orderGoodsVo);
        });

        List<OrderGoodsVo> ordergoodsVolist = new ArrayList<>();
        Map<Integer, List<OrderGoodsVo>> collect = orderGoodsVos.stream().collect(Collectors.groupingBy(OrderGoodsVo::getCategoryId));
        collect.keySet().forEach(key->{
            List<OrderGoodsVo> lrgs = collect.get(key);
            if(lrgs.size()>1){
                OrderGoodsVo orderGoodsVo = new OrderGoodsVo();
                BeanUtils.copyProperties(lrgs.get(0), orderGoodsVo);
                orderGoodsVo.setNumber((short)(lrgs.stream().mapToInt(OrderGoodsVo::getNumber).sum()));
                ordergoodsVolist.add(orderGoodsVo);
            }else{
                ordergoodsVolist.add(lrgs.get(0));
            }
        });
        return ordergoodsVolist;
    }

    /**
     * 得到订单货物
     * //商品订单 分组求和
     *
     * @param orderGoodsList 订单商品列表
     * @return {@link List}<{@link LitemallOrderGoods}>
     */
    private List<LitemallOrderGoods> getOrderGoods(List<LitemallOrderGoods> orderGoodsList) {
        List<LitemallOrderGoods> orderGoodss = new ArrayList<>();
        Map<Integer, List<LitemallOrderGoods>> collect = orderGoodsList.stream().collect(Collectors.groupingBy(LitemallOrderGoods::getGoodsId));
        collect.keySet().forEach(key->{
            List<LitemallOrderGoods> lrgs = collect.get(key);
            if(lrgs.size()>1){
                LitemallOrderGoods orderGoods = new LitemallOrderGoods();
                BeanUtils.copyProperties(lrgs.get(0), orderGoods);
                int intStream = lrgs.stream().mapToInt(LitemallOrderGoods::getNumber).sum();
                orderGoods.setNumber((short)intStream);
                orderGoodss.add(orderGoods);
            }else{
                orderGoodss.add(lrgs.get(0));
            }
        });
        return orderGoodss;
    }

    /**
     * 余额退款
     * 退款到余额
     *
     * @param orderId 订单id
     * @return boolean
     */
    public boolean balanceRefund(Integer orderId){
            LitemallOrder order = litemallOrderService.findById(orderId);
            Integer userId = order.getUserId();
            LitemallUser user = userService.findById(userId);
            user.setUpdateTime(LocalDateTime.now());
            user.setAvailableAmount(user.getAvailableAmount().add(order.getActualPrice()));
            //userService.updateWithOptimisticLocker(user, user.getUpdateTime());

            //是否使用优惠券，如果有，就返还优惠券
            /*List<LitemallCouponUser> couponUsers = litemallCouponUserService.queryByOrderId(order.getId());
            if(couponUsers.size() > 0 && couponUsers.get(0) != null){
                couponUsers.get(0).setStatus(CouponUserConstant.STATUS_USABLE);
                couponUsers.get(0).setUsedTime(null);
                litemallCouponUserService.update(couponUsers.get(0));
            }*/

            LitemallRechargeConsumption log = new LitemallRechargeConsumption();
            log.setOrderId(order.getId());
            log.setAmount(order.getActualPrice());
            log.setAddUserId(user.getId());
            log.setUserId(user.getId());
            log.setUsername(user.getUsername());
            log.setMobile(user.getMobile());
            log.setPoints(user.getPoints());
            log.setType(org.linlinjava.litemall.db.beans.Constants.LOG_GIFTCARD_REFUND);
            log.setUserLevel(user.getUserLevel());
            log.setAvailableAmount(user.getAvailableAmount().add(order.getActualPrice()));
            log.setOrderSource(Constants.ORDER_SOURCE_APP);
            litemallRechargeConsumptionService.add(log);
            return userService.updateById(user);
    }

    /**
     * 礼品卡退款
     * 退款到礼物卡
     *
     * @param orderId 订单id
     * @return boolean
     */
    public boolean giftCardRefund(Integer orderId){
            LitemallOrder order = litemallOrderService.findById(orderId);
            LitemallGiftCardUserLog userLog =  litemallGiftCardUserLogService.queryByOrderIdAndType(orderId,(byte)2);
            Integer cardId = userLog.getCardUserId();
            LitemallGiftCardUser card = litemallGiftCardUserService.findById(cardId);
            card.setAmount(card.getAmount().add(order.getActualPrice()));
            litemallGiftCardUserService.updateById2(card);
            //litemallGiftCardUserService.updateWithOptimisticLocker(card, card.getUpdateTime());
            //是否使用优惠券，如果有，就返还优惠券
            /*List<LitemallCouponUser> couponUsers = litemallCouponUserService.queryByOrderId(order.getId());
            if(couponUsers.size() > 0 && couponUsers.get(0) != null){
                couponUsers.get(0).setStatus(CouponUserConstant.STATUS_USABLE);
                couponUsers.get(0).setUsedTime(null);
                litemallCouponUserService.update(couponUsers.get(0));
            }*/
            LitemallGiftCardUserLog log = new LitemallGiftCardUserLog();
            log.setAmount(order.getActualPrice());
            log.setAddUserId(order.getUserId());
            log.setType(org.linlinjava.litemall.db.beans.Constants.LOG_GIFTCARD_REFUND);
            log.setCardNumber(card.getCardNumber());
            log.setContent("退款");
            log.setCardUserId(card.getId());
            log.setBalance(card.getAmount());
            log.setOrderId(orderId);
            log.setCardUserId(userLog.getCardUserId());
            log.setOrderSource(org.linlinjava.litemall.db.beans.Constants.ORDER_SOURCE_APP);
            log.setChangePoints(order.getPoints());
            litemallGiftCardUserLogService.add(log);
        return true;
    }

    /**
     * 点交易退款
     *
     * @param orderId 订单id
     * @return boolean
     */
    public boolean pointExchangeRefund(Integer orderId){
            LitemallOrder order = litemallOrderService.findById(orderId);
            //查看并更新用户积分
            LitemallUser user = userService.findById(order.getUserId());
            user.setPoints(user.getPoints().add(order.getPoints()));
            if(!userService.updateById(user)){
               return false;
            }

            LitemallIntegralLog l = new LitemallIntegralLog();
            l.setUserId(user.getId());
            l.setType(INTEGRAL_LOG_TYPE_RETURN);
            l.setOrderId(orderId);
            l.setPoints(user.getPoints());
            l.setChangePoints(order.getPoints());
            //添加详细信息
            l.setUseType(6);
            l.setGoodsName(orderGoodsService.queryByOid(orderId).stream().map(litemallOrderGoods -> litemallOrderGoods.getGoodsName()).collect(Collectors.toList()));
            integralLogService.add(l);
        return true;
    }

    /**
     * 收货人
     * 修改收货人
     *
     * @param body   身体
     * @param shopId 商店id
     * @return {@link Object}
     */
    public Object consignee(String body, Integer shopId) {
    	Integer orderId = JacksonUtil.parseInteger(body, "orderId");
    	String consignee = JacksonUtil.parseString(body, "consignee");
    	String mobile = JacksonUtil.parseString(body, "mobile");
    	String address = JacksonUtil.parseString(body, "address");
    	if (orderId == null || orderId == 0) {
    		return ResponseUtil.badArgument();
    	}
    	LitemallOrder order = litemallOrderService.findById(orderId);
    	if (order == null) {
    		return ResponseUtil.fail(ORDER_NOT_EXIST, "订单不存在！");
    	}
    	LitemallOrder update = new LitemallOrder();
    	update.setId(orderId);
    	if(!StringUtils.isEmpty(consignee)){
    		update.setConsignee(consignee);
    	}
    	if(!StringUtils.isEmpty(mobile)) {
    		update.setMobile(mobile);
    	}
    	if(!StringUtils.isEmpty(address)) {
    		update.setAddress(address);
    	}
    	litemallOrderService.updateById(update);
    	return ResponseUtil.ok();
    }

    /**
     * 订单月统计数据
     * 按月统计
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param regionId  区域id
     * @param shopId    商店id
     * @param page      页面
     * @param limit     限制
     * @return {@link Object}
     */
    public Object orderMonthStatistics(String startTime, String endTime, Integer regionId, Integer shopId, Integer page, Integer limit) {
        // 解析日期字符串
        LocalDate date = LocalDate.parse(endTime.substring(0, 10)); // 截取日期部分
        // 减去一天
        LocalDate newDate = date.minusDays(1);
        // 格式化为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String endDate = newDate.format(formatter);
        List<OrderMonthStatisticsVo> result = litemallOrderService.monthStatistics(startTime, endDate, regionId, shopId, page, limit);
    	if(!CollUtil.isEmpty(result)) {
    		for (OrderMonthStatisticsVo orderMonthStatisticsVo : result) {
    			List<TaxStatisticsDetailVo> taxDetailLs = litemallOrderTaxService.monthStatistics(startTime, endTime, orderMonthStatisticsVo.getShopId());
    			orderMonthStatisticsVo.setTaxDetailLs(taxDetailLs);
    		}
    	}
    	return ResponseUtil.okList(result);
    }


    public ResponseUtil.Response orderDayStatistics(AdminShopOrderDayStatisticsPageReqVO pageReqVO) {
    	if (pageReqVO.getShopId() == null || pageReqVO.getShopId() == 0 ) {
    		return ResponseUtil.badArgument();
    	}

        IPage<OrderDayStatisticsVo> result = getOrderStatisticsWithPage(pageReqVO);
    	if(!CollUtil.isEmpty(result.getRecords())) {
            result.getRecords().forEach(orderMonthStatisticsVo->{
                List<TaxStatisticsDetailVo> taxDetailLs = litemallOrderTaxService.dayStatistics(pageReqVO.getShopId(), orderMonthStatisticsVo.getDate());
                orderMonthStatisticsVo.setTaxDetailLs(taxDetailLs);
            });
    	}
    	return ResponseUtil.okPage(result);
    }

    public IPage<OrderDayStatisticsVo> getOrderStatisticsWithPage(AdminShopOrderDayStatisticsPageReqVO pageReqVO) {
        LambdaQueryWrapper<LitemallOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(LitemallOrder::getOrderStatus, 401,201)
                .isNull(LitemallOrder::getPayMemberId)
                .isNull(LitemallOrder::getExternalId)
                .isNull(LitemallOrder::getExId)
                .eq(LitemallOrder::getDeleted, false)
                .isNotNull(LitemallOrder::getPayTime);

        if (pageReqVO.getOrderSource() != null && pageReqVO.getOrderSource() != 0) {
            queryWrapper.eq(LitemallOrder::getOrderSource, pageReqVO.getOrderSource());
        }
        if (pageReqVO.getShopId() != null) {
            queryWrapper.eq(LitemallOrder::getShopId, pageReqVO.getShopId());
        }
        Optional.ofNullable(pageReqVO.getDateRange())
                .filter(arr -> arr.length == 2 && arr[0] != null && arr[1] != null)
                .ifPresent(range -> queryWrapper.between(LitemallOrder::getUpdateTime, range[0], range[1]));

        // 数据库分页
        IPage<LitemallOrder> pagedOrders = litemallOrderService.page(new Page<>(pageReqVO.getPage(), pageReqVO.getLimit()), queryWrapper);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 分组统计（只对当前页数据）
        Map<String, List<LitemallOrder>> groupedOrders = pagedOrders.getRecords().stream()
                .collect(Collectors.groupingBy(order -> order.getPayTime().format(formatter)));

        List<OrderDayStatisticsVo> result = groupedOrders.entrySet().stream()
                .map(entry -> {
                    String date = entry.getKey();
                    List<LitemallOrder> orderList = entry.getValue();

                    OrderDayStatisticsVo vo = new OrderDayStatisticsVo();
                    vo.setDate(date);
                    vo.setTotalCount(orderList.size());
                    vo.setTotalAmount(orderList.stream()
                            .map(LitemallOrder::getOrderPrice)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));
                    vo.setTaxTotalAmount(orderList.stream()
                            .map(LitemallOrder::getTaxPrice)
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));

                    return vo;
                })
                .sorted(Comparator.comparing(OrderDayStatisticsVo::getDate).reversed())
                .collect(Collectors.toList());

        // 封装分页返回
        IPage<OrderDayStatisticsVo> resultPage = new Page<>();
        resultPage.setCurrent(pagedOrders.getCurrent());
        resultPage.setSize(pagedOrders.getSize());
        resultPage.setTotal(pagedOrders.getTotal());
        resultPage.setRecords(result);

        return resultPage;
    }

    public Object orderHourStatisticsLine(HourStatisticsLineReqVO reqVO) {
        List<List<OrderHourStatisticsVo>> lineList = new ArrayList<>();
        for (String searchDate : reqVO.getSearchDateList()) {
            // 1. 查询符合条件的订单
            LambdaQueryWrapper<LitemallOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(LitemallOrder::getOrderStatus, Constants.ORDER_STATUS_FINISHED)
                    .eq(reqVO.getShopId() != null, LitemallOrder::getShopId, reqVO.getShopId())
                    .isNull(LitemallOrder::getPayMemberId)
                    .isNull(LitemallOrder::getExternalId)
                    .isNull(LitemallOrder::getExId)
                    .eq(LitemallOrder::getDeleted, 0);
            lambdaQueryWrapper.apply("DATE(pay_time) = {0}", searchDate); // 筛选特定日期的订单
// 查询订单列表
            List<LitemallOrder> orderList = litemallOrderService.selectList(lambdaQueryWrapper);

// 2. 获取订单的最早和最晚支付时间，生成所有可能的时间段
            LocalDateTime earliestTime;
            LocalDateTime latestTime;

// 如果没有订单，使用当天的时间范围
            if (orderList.isEmpty()) {
                // 获取今天的日期
                LocalDate today = LocalDate.now();  // 当前日期
                earliestTime = today.atStartOfDay();  // 当天的开始时间 (00:00:00)
                latestTime = today.atTime(23, 59, 59);  // 当天的结束时间 (23:59:59)
            } else {
                // 如果有订单，使用最早和最晚的支付时间
                earliestTime = orderList.stream()
                        .map(LitemallOrder::getPayTime)
                        .min(LocalDateTime::compareTo)
                        .orElseThrow(() -> new RuntimeException("没有订单数据"));

                latestTime = orderList.stream()
                        .map(LitemallOrder::getPayTime)
                        .max(LocalDateTime::compareTo)
                        .orElseThrow(() -> new RuntimeException("没有订单数据"));
            }

// 3. 按照时间间隔生成所有时间段
            List<LocalDateTime> timeSlots = new ArrayList<>();
            LocalDateTime currentTime = earliestTime.truncatedTo(ChronoUnit.MINUTES); // 将时间精确到分钟
            while (currentTime.isBefore(latestTime) || currentTime.equals(latestTime)) {
                timeSlots.add(currentTime);
                currentTime = currentTime.plusMinutes(reqVO.getTime()); // 增加时间间隔
            }


// 4. 按照 pay_time 分组，时间间隔为 time 分钟
            Map<String, OrderHourStatisticsVo> orderCountMap = new HashMap<>();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

            for (LitemallOrder order : orderList) {
                LocalDateTime payTime = order.getPayTime();
                // 将支付时间按每 `time` 分钟取整
                long minutes = payTime.getMinute() / reqVO.getTime() * reqVO.getTime(); // 取整
                LocalDateTime timeSlot = payTime.withMinute((int) minutes).withSecond(0).withNano(0);

                String timeSlotString = timeSlot.format(formatter); // 格式化时间为字符串

                // 获取该时间段的统计对象，如果没有则新建
                OrderHourStatisticsVo stats = orderCountMap.computeIfAbsent(timeSlotString, k -> new OrderHourStatisticsVo());
                stats.setDate(timeSlotString);

                // 累加订单数量
                stats.setTotalCount(stats.getTotalCount() + 1);

                // 累加订单总额
                stats.setTotalAmount(stats.getTotalAmount().add(order.getOrderPrice() != null ? order.getOrderPrice() : BigDecimal.ZERO));

                // 累加税费总额
                stats.setTaxTotalAmount(stats.getTaxTotalAmount().add(order.getTaxPrice() != null ? order.getTaxPrice() : BigDecimal.ZERO));

                // 记录订单ID
                stats.addOrderId(order);
            }

// 5. 填充没有订单的时间段
            for (LocalDateTime slot : timeSlots) {
                String timeSlotString = slot.format(formatter);
                if (!orderCountMap.containsKey(timeSlotString)) {
                    OrderHourStatisticsVo emptyStats = new OrderHourStatisticsVo();
                    emptyStats.setDate(timeSlotString);
                    orderCountMap.put(timeSlotString, emptyStats);
                }
            }

// 6. 将结果转换为 List 返回
            List<OrderHourStatisticsVo> resultList = new ArrayList<>(orderCountMap.values());

// 7. 按时间段排序
            resultList.sort(Comparator.comparing(OrderHourStatisticsVo::getDate));

            lineList.add(resultList);
        }
        return ResponseUtil.ok(lineList);
    }


    public Object orderHourStatistics(String searchDate, Integer time, Integer shopId, Integer page, Integer limit) {
    	if (shopId == null || shopId == 0 ) {
    		return ResponseUtil.badArgument();
    	}

        // 1. 查询符合条件的订单
        LambdaQueryWrapper<LitemallOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LitemallOrder::getOrderStatus,Constants.ORDER_STATUS_FINISHED)
                .eq(LitemallOrder::getShopId,shopId)
                .isNull(LitemallOrder::getPayMemberId)
                .isNull(LitemallOrder::getExternalId)
                .isNull(LitemallOrder::getExId)
                .eq(LitemallOrder::getDeleted,0);
        lambdaQueryWrapper.apply("DATE(pay_time) = {0}", searchDate);// 筛选特定日期的订单
        // 查询订单列表
        IPage<LitemallOrder> orderList = litemallOrderService.page(new Page<>(page,limit),lambdaQueryWrapper);

        // 2. 按照 pay_time 分组，时间间隔为 time 分钟
        Map<String, OrderHourStatisticsVo> orderCountMap = new HashMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        for (LitemallOrder order : orderList.getRecords()) {
            LocalDateTime payTime = order.getPayTime();
            // 将支付时间按每 `time` 分钟取整
            long minutes = payTime.getMinute() / time * time; // 取整
            LocalDateTime timeSlot = payTime.withMinute((int) minutes).withSecond(0).withNano(0);

            String timeSlotString = timeSlot.format(formatter); // 格式化时间为字符串


            // 获取该时间段的统计对象，如果没有则新建
            OrderHourStatisticsVo stats = orderCountMap.computeIfAbsent(timeSlotString, k -> new OrderHourStatisticsVo());
            stats.setDate(timeSlotString);

            // 累加订单数量
            stats.setTotalCount(stats.getTotalCount() + 1);

            // 累加订单总额
            stats.setTotalAmount(stats.getTotalAmount().add(order.getOrderPrice() != null ? order.getOrderPrice() : BigDecimal.ZERO));

            // 累加税费总额
            stats.setTaxTotalAmount(stats.getTaxTotalAmount().add(order.getTaxPrice() != null ? order.getTaxPrice() : BigDecimal.ZERO));

            // 记录订单ID
            stats.addOrderId(order);
        }

        // 3. 查询每个时间段的商品数量
        for (Map.Entry<String, OrderHourStatisticsVo> entry : orderCountMap.entrySet()) {
            List<LitemallOrder> orderTimeList = entry.getValue().getOrderList();
            if(CollUtil.isEmpty(orderTimeList)){
                // 设置商品数量到对应的统计对象
                entry.getValue().setProductCount(0);
            }

            // 查询订单商品数量
            int productCount = 0;
            for (LitemallOrder order : orderTimeList) {
                List<LitemallOrderGoods> orderGoodsList = CollUtil.isNotEmpty(order.getGoodsIds())?orderGoodsService.getOrderGoodsByIds(order.getGoodsIds()):CollUtil.newArrayList();
                for (LitemallOrderGoods orderGoods : orderGoodsList) {
                    productCount+=orderGoods.getNumber();
                }

                List<LitemallOrderPackage> orderPackageList = CollUtil.isNotEmpty(order.getPackageIds())?litemallOrderPackageService.listByIds(order.getPackageIds()):CollUtil.newArrayList();
                for (LitemallOrderPackage orderPackage : orderPackageList) {
                    productCount+=orderPackage.getNumber()*orderPackage.getGoodsIds().size();
                }
            }

            // 设置商品数量到对应的统计对象
            entry.getValue().setProductCount(productCount);
        }

        // 4. 将结果转换为 List 返回
        List<OrderHourStatisticsVo> resultList = new ArrayList<>(orderCountMap.values());

        // 按时间段排序
        resultList.sort(Comparator.comparing(OrderHourStatisticsVo::getDate));

        //List<OrderHourStatisticsVo> result = litemallOrderService.hourStatistics(searchDate,time, shopId, page, limit);
    	if(!CollUtil.isEmpty(resultList)) {
    		for (OrderHourStatisticsVo orderMonthStatisticsVo : resultList) {
    			List<TaxStatisticsDetailVo> taxDetailLs = litemallOrderTaxService.hourStatistics(shopId,String.valueOf(time), orderMonthStatisticsVo.getDate());
    			orderMonthStatisticsVo.setTaxDetailLs(taxDetailLs);
    		}
    	}
    	return ResponseUtil.okList(resultList);
    }


    public Object orderDayStatisticsDetail(OrderDayDetailReqVO reqVO) {
    	if (reqVO.getShopId()==null ||StrUtil.isEmpty(reqVO.getSearchDate())) {
    		return ResponseUtil.badArgument();
    	}
        //用户账号
    	List<Integer> userIds = StrUtil.isEmpty(reqVO.getUserName())?null:
                CollStreamUtil.toList(userService.findByName(reqVO.getUserName()),LitemallUser::getId);

        DateTimeFormatter timeDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List result = new ArrayList<>();

        // 构建查询条件
        LambdaQueryWrapper<LitemallOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CollUtil.isNotEmpty(userIds),LitemallOrder::getUserId,userIds);
        queryWrapper.like(StrUtil.isNotEmpty(reqVO.getOrderSn()),LitemallOrder::getOrderSn,reqVO.getOrderSn());
        queryWrapper.eq(LitemallOrder::getShopId,reqVO.getShopId());
        queryWrapper.in(CollUtil.isNotEmpty(reqVO.getPayTypes()),LitemallOrder::getPayType,reqVO.getPayTypes());
        queryWrapper.in(CollUtil.isNotEmpty(reqVO.getOrderSources()),LitemallOrder::getOrderSource,reqVO.getOrderSources());
        queryWrapper.in(CollUtil.isNotEmpty(reqVO.getOrderTypes()),LitemallOrder::getOrderType,reqVO.getOrderTypes());

        //queryWrapper.eq(LitemallOrder::getOrderStatus,Constants.ORDER_STATUS_FINISHED);

        //queryWrapper.between(StrUtil.isNotEmpty(reqVO.getSearchDate()),LitemallOrder::getPayTime,LocalDateTime.of(LocalDate.parse(reqVO.getSearchDate(), timeDtf), LocalTime.MIN),LocalDateTime.of(LocalDate.parse(reqVO.getSearchDate(), timeDtf), LocalTime.MAX));
        queryWrapper.orderByDesc(LitemallOrder::getAddTime);
        IPage<LitemallOrder> litemallOrders = litemallOrderService.page(new Page<>(reqVO.getPage(), reqVO.getLimit()),queryWrapper);
    	//List<LitemallOrder> litemallOrders = litemallOrderService.dayStatisticDetail(searchDate, shopId, userIds, orderSn, page, limit);
    	if(!CollUtil.isEmpty(litemallOrders.getRecords())) {
    		for (LitemallOrder order : litemallOrders.getRecords()) {
    			OrderDayStatisticDetailVo orderDayStatisticDetailVo = new OrderDayStatisticDetailVo();
    			BeanUtils.copyProperties(order, orderDayStatisticDetailVo);

    			Integer userId = order.getUserId();
    			if(null != userId) {
                    LitemallUser user = userService.findById(userId);
                    orderDayStatisticDetailVo.setUserName(user.getUsername());
                    orderDayStatisticDetailVo.setNikeName(user.getNickname());
    			}

    			//List<TaxStatisticsDetailVo> taxDetailLs = litemallOrderTaxService.dayStatisticsByOrderId(order.getId());
    			//orderDayStatisticDetailVo.setTaxDetailLs(taxDetailLs);

    			result.add(orderDayStatisticDetailVo);
    		}
    	}
        litemallOrders.setRecords(result);
    	return ResponseUtil.okPage(litemallOrders);
    }

    /**
     * 订单总额统计
     * 汇总数统计
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param regionId  区域id
     * @param shopId    商店id
     * @return {@link Object}
     */
    public Object orderTotalStatistics(String startTime, String endTime, Integer regionId, Integer shopId) {
        //交易
    	OrderTotalStatisticsVo result = litemallOrderService.totalStatistics(startTime, endTime, regionId, shopId);
    	List<TaxStatisticsDetailVo> taxDetailLs = litemallOrderTaxService.totalStatistics(startTime, endTime, shopId, regionId,401);
        //退款
        OrderRefundTotalStatisticsVo orderRefundTotalStatisticsVo = litemallOrderService.refundTotalStatistics(startTime, endTime, regionId, shopId);
        result.setRefundTotalAmount(orderRefundTotalStatisticsVo.getRefundTotalAmount());
        result.setTaxRefundTotalAmount(orderRefundTotalStatisticsVo.getTaxRefundTotalAmount());
        //税费退款明细
        result.setTaxRefundDetailLs(litemallOrderTaxService.totalStatistics(startTime, endTime, shopId, regionId,203));
        //税费交易明细
        result.setTaxDetailLs(taxDetailLs);
        //总订单
        result.setTotalCount(result.getTotalCount());
    	return ResponseUtil.ok(result);
    }

    /**
     * 得到评论
     * 查询订单备注信息
     *
     * @param orderId 订单id
     * @return {@link List}<{@link LitemallOrderRecord}>
     */
    public List<LitemallOrderRecord> getRemarks(Integer orderId) {
    	return orderRecordService.querySelective(orderId, 1, Integer.MAX_VALUE, "add_time", "desc");
    }

    /**
     * 退款细节
     * 退款
     *
     * @param shopId      操作店铺id
     * @param goods       <退款订单商品,退款数量>集合
     * @param userId      用户id
     * @param deviceNo    设备没有
     * @param outRefundId 了退款id
     * @param order       订单
     * @return {@link Integer}
     */
    @Async
    public Integer refundDetail(Integer shopId, Integer userId, String deviceNo, String outRefundId, LitemallOrder order, List<Pair<LitemallOrderGoods, Integer>> goods) {
        Integer orderId = order.getId();

        //创建退款
        LitemallRefund refund = new LitemallRefund();
        refund.setOrderId(orderId);
        refund.setOrderShopId(order.getShopId());
        refund.setRefundShopId(shopId);
        refund.setOrderSn(order.getOrderSn());
        refund.setRefundSn(generateRefundSn());
        refund.setUserId(order.getUserId());
        refund.setOutRefundId(outRefundId);
        refund.setDeviceNo(deviceNo);
        Byte payType = order.getPayType();
        refund.setRefundType(payType);
        refund.setRefundState(org.linlinjava.litemall.db.beans.Constants.REFUND_STATUS_SUCCESS);//退款中
        refund.setAddUserId(userId);
        litemallRefundService.add(refund);

        Integer refundId = refund.getId();
        //查询订单商品
        BigDecimal goodsPrice = BigDecimal.ZERO;
        BigDecimal taxPrice = BigDecimal.ZERO;
        BigDecimal totalPrice = BigDecimal.ZERO;
        Integer canOrderRefundNumber = 0;
        for (Pair<LitemallOrderGoods, Integer> pair : goods) {
            LitemallOrderGoods orderGoods = pair.getLeft();
            Integer refundNumber = pair.getRight();
            Integer orderGoodsId = orderGoods.getId();

            //更新订单商品的总退款数量
            Integer totalRefundNumber = orderGoods.getRefundNumber() + refundNumber;
            Integer lastRefundNumber = orderGoods.getNumber() - totalRefundNumber;
            //计算订单的可退款商品的数量
            canOrderRefundNumber = canOrderRefundNumber + lastRefundNumber;

            //如果商品的可退款数量为0，且订单为待制作状态，则订单商品的制作状态修改为制作完成
            if(org.linlinjava.litemall.db.beans.Constants.ORDER_STATUS_ONGOING == order.getOrderStatus()
                    && org.linlinjava.litemall.db.beans.Constants.ORDER_MADE_STATUS_NEW == order.getMadeStatus() && lastRefundNumber == 0) {
                orderGoods.setMadeStatus(org.linlinjava.litemall.db.beans.Constants.ORDER_GOODS_MADE_STATUS_FINISHED);
            }
            orderGoods.setRefundNumber(totalRefundNumber.shortValue());
            orderGoodsService.updateById(orderGoods);

            //创建退款商品
            LitemallRefundGoods refundGoods = new LitemallRefundGoods();
            refundGoods.setRefundId(refundId);
            refundGoods.setOrderId(orderId);
            refundGoods.setOrderGoodsId(orderGoodsId);
            refundGoods.setGoodsId(orderGoods.getGoodsId());
            refundGoods.setNumber(refundNumber.shortValue());
            refundGoods.setUnitPrice(orderGoods.getDiscountPrice());
            BigDecimal refundGoodsPrice = orderGoods.getDiscountPrice().multiply(new BigDecimal(refundNumber));
            refundGoods.setGoodsPrice(refundGoodsPrice);
            litemallRefundGoodsService.add(refundGoods);
            Integer refundGoodsId = refundGoods.getId();

            //创建退款税费
            BigDecimal refundTaxPrice = BigDecimal.ZERO;
            List<LitemallOrderTax> orderTaxs = litemallOrderTaxService.queryByOrderIdAndOrderGoodsId(orderId, orderGoodsId);
            if(!CollUtil.isEmpty(orderTaxs)) {
                for (LitemallOrderTax orderTax : orderTaxs) {
                    LitemallRefundTax refundTax = new LitemallRefundTax();
                    refundTax.setRefundId(refundId);
                    refundTax.setRefundGoodsId(refundGoodsId);
                    refundTax.setCode(orderTax.getCode());
                    BigDecimal value = orderTax.getValue();
                    refundTax.setValue(value);
                    //计算code为GST或其他的税费是多少
                    BigDecimal price = refundGoodsPrice.multiply(value).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    refundTax.setPrice(price);
                    litemallRefundTaxService.add(refundTax);

                    refundTaxPrice = refundTaxPrice.add(price);
                }
            }

            //修改退款商品的税费
            refundGoods.setTaxPrice(refundTaxPrice);
            refundGoods.setPrice(refundGoodsPrice.add(refundTaxPrice));
            litemallRefundGoodsService.update(refundGoods);

            goodsPrice = goodsPrice.add(refundGoodsPrice);
            taxPrice = taxPrice.add(refundTaxPrice);
        }
        totalPrice = goodsPrice.add(taxPrice);
        //实际支付金额
        BigDecimal actualPrice = totalPrice;

        //更新退款金额
        refund.setGoodsPrice(goodsPrice);
        refund.setTaxPrice(taxPrice);
        refund.setPrice(totalPrice);
        refund.setActualPrice(actualPrice);
        litemallRefundService.update(refund);

        if(canOrderRefundNumber == 0) {
            //待制作状态的订单全部退款，则将订单状态设置为完成
            if(org.linlinjava.litemall.db.beans.Constants.ORDER_STATUS_ONGOING == order.getOrderStatus()
                    && org.linlinjava.litemall.db.beans.Constants.ORDER_MADE_STATUS_NEW == order.getMadeStatus()) {
                order.setOrderStatus(org.linlinjava.litemall.db.beans.Constants.ORDER_STATUS_FINISHED);
            }

            if(org.linlinjava.litemall.db.beans.Constants.ORDER_PAY_TYPE_CASH == payType
                    || org.linlinjava.litemall.db.beans.Constants.ORDER_PAY_TYPE_BALANCE == payType
                    || org.linlinjava.litemall.db.beans.Constants.ORDER_PAY_TYPE_CARD == payType) {
                //设置退款成功
                order.setRefundStatus(org.linlinjava.litemall.db.beans.Constants.ORDER_REFUND_STATUS_SUCCESS);
            }
            //更新订单是否退款字段
//            order.setOrderStatus(OrderStatusUtil.STATUS_REFUND_CONFIRM);
            order.setIsRefund(true);

        }
        litemallOrderService.updateById(order);
        return refundId;

    }

    /**
     * 生成退款sn
     *
     * @return {@link String}
     */
    private String generateRefundSn() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String now = df.format(LocalDateTime.now());
        return "T" + now + RandomStringUtils.randomAlphanumeric(4);
    }

    /**
     * 订单类型统计
     *
     * @param payType     支付类型
     * @param shopId      商店id
     * @param orderSource 订单来源
     * @param page        页面
     * @param limit       限制
     * @return {@link ResponseUtil.Response}
     */
    public ResponseUtil.Response orderTypeStatistics(Integer payType,Integer shopId, Integer orderSource,Integer page, Integer limit) {
        IPage<LitemallOrder> litemallOrders = litemallOrderService.selectJoinListPage(new Page<>(page, limit),LitemallOrder.class, new MPJLambdaWrapper<LitemallOrder>()
                .selectAll(LitemallOrder.class)
                .selectAs(LitemallUser::getUsername, LitemallOrder::getUsername)
                .selectAs(LitemallShop::getName, LitemallOrder::getShopName)
                .leftJoin(LitemallUser.class, LitemallUser::getId, LitemallOrder::getUserId)
                .leftJoin(LitemallShop.class, LitemallShop::getId, LitemallOrder::getShopId)
                .eq(ObjectUtil.isNotEmpty(payType), LitemallOrder::getPayType, payType)
                .eq(ObjectUtil.isNotEmpty(shopId), LitemallOrder::getShopId, shopId)
                .eq(ObjectUtil.isNotEmpty(orderSource), LitemallOrder::getOrderSource, orderSource)
                .orderByDesc(LitemallOrder::getAddTime)
        );
        return ResponseUtil.okPage(litemallOrders);
       /* List<LitemallOrder> litemallOrderList = litemallOrderService.list(Wrappers.lambdaQuery(LitemallOrder.class)
                .eq(ObjectUtil.isNotEmpty(payType),LitemallOrder::getPayType, payType)
                .eq(ObjectUtil.isNotEmpty(shopId),LitemallOrder::getShopId, shopId)
                .eq(ObjectUtil.isNotEmpty(orderSource),LitemallOrder::getOrderSource, orderSource)
                .orderByDesc(LitemallOrder::getAddTime)
        );
        litemallOrderList.stream().forEach(litemallOrder -> {
            LitemallUser litemallUser = userService.findById(litemallOrder.getUserId());
            litemallOrder.setUsername(ObjectUtil.isNotNull(litemallUser)?litemallUser.getUsername():"");
            litemallOrder.setShopName(litemallOrder.getShopId()!=null?shopService.findById(litemallOrder.getShopId()).getName():null);
        });
        Pageable pageable = PageRequest.of(page -1 ,limit);
        return ResponseUtil.ok(PageUtil.getPageLumierePayMemberUserLogVo(pageable,litemallOrderList));*/
    }

    public ResponseUtil.Response userOrderMemberList(Integer userId, Integer page, Integer limit) {
        IPage<LitemallOrder> orderList = litemallOrderService.selectJoinListPage(new Page<>(page,limit),LitemallOrder.class,new MPJLambdaWrapper<LitemallOrder>()
                .selectAll(LitemallOrder.class)
                .selectAs(LitemallShop::getName,LitemallOrder::getShopName)
                .leftJoin(LitemallShop.class,LitemallShop::getId,LitemallOrder::getShopId)
                .eq(LitemallOrder::getUserId, userId)
                .orderByDesc(LitemallOrder::getAddTime));
        return ResponseUtil.okPage(orderList);
    }


    public Object goodsBrowser() {
        //获取所有商品的浏览量
        return ResponseUtil.ok(browseRecordService.goodsBrowser(LocalDateTime.now()));
    }



}
